//
// Copyright (c) 2010 Luís Reis
//
// MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
using System;
namespace Pine.Core
{
	public class Value
	{
		public Value ()
		{
		}
		
		public virtual bool IsCallable {
			get { return false; }
		}
		
		public virtual void Invoke(ValueList rightlist) {
			throw new PineException("Invalid value call [" + GetType().FullName + "]");
		}
		
		public virtual Value Add(Value right) {
			throw new PineException("Meaningless operation + (right=" + right.GetType() + ")");	
		}
		
		public virtual Value Subtract(Value right) {
			throw new PineException("Meaningless operation -");	
		}
		
		public virtual Value Multiply(Value right) {
			if (right == null)
				throw new ArgumentNullException("right", "Right operand of multiplication is null (not NullValue)");
			
			string err = "Meaningless operation multiplication between [";
			err += this.GetType().Name;
			err += "] and [";
			err += right.GetType().Name;
			err += "]";
			throw new PineException(err);	
		}
		
		public virtual Value Greater(Value right) {
			throw new PineException("Meaningless operation >");
		}
		
		public virtual Value GreaterOrEqual(Value right) {
			throw new PineException("Meaningless operation >=");	
		}
		
		public virtual Value Less(Value right) {
			throw new PineException("Meaningless operation <");	
		}
		
		public virtual Value LessOrEqual(Value right) {
			throw new PineException("Meaningless operation <=");	
		}
		
		public virtual Value IsEqualTo(Value right) {
			return new BooleanValue(Equals(right));	
		}
		
		public virtual Value NotEqualTo(Value right) {
			return new BooleanValue(!Equals(right));
		}
		
		public virtual Value FieldGet(string fieldname) {
			throw new PineException("Meaningless operation: field get for type " + GetType().FullName + ", field " + fieldname);	
		}
		
		public virtual void FieldSet(string fieldname, Value value) {
			throw new PineException("Meaningless operation: field set");
		}
		
		public virtual Value Increment() {
			throw new PineException("Meaningless operation: increment");	
		}
		
		public virtual Value Decrement() {
			throw new PineException("Meaningless operation: decrement");
		}
		
		public virtual Value Positive() {
			throw new PineException("Meaningless operation: positive");
		}
		
		public virtual Value Negative() {
			throw new PineException("Meaningless operation: negative");
		}
		
		public virtual Value BitwiseNot() {
			throw new PineException("Meaningless operation: Bitwise Not");
		}
		
		public virtual Value LogicalNot() {
			return new BooleanValue(!ToBoolean());
		}
		
		public virtual Value GetArrayElement(Value key)
		{
			throw new PineException("Meaningless operation: array get");
		}
		public virtual void SetArrayElement(Value key, Value value) {
			throw new PineException("Meaningless operation: array set for " + ToString());
		}
		
		public virtual Value GetPineType() {
			throw new PineException("Unknown type for " + this.GetType().FullName);
		}
		
		public virtual bool ToBoolean() {
			return true;	
		}
		
		public bool IsNull() {
			return GetType()==typeof(NullValue);
		}
	}
}

